package com.hydra.base.global;

import com.hydra.base.annotations.IgnoreResponseResult;
import com.hydra.base.resp.Response;
import com.hydra.base.resp.ResultError;
import com.hydra.base.utils.AnnotationUtil;
import com.hydra.base.utils.JsonUtil;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import reactor.util.annotation.NonNull;

import java.lang.reflect.Method;

/**
 * 封装全局返回对象
 * @Author Hydra
 * @Date 2022/4/18 15:24
 */
@RestControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {

    /**
     * 判断方法有无返回类型，有则调用 beforeBodyWrite 方法
     */
    @Override
    public boolean supports(MethodParameter returnType, @NonNull Class<? extends HttpMessageConverter<?>> converterType) {
        Method method = returnType.getMethod();
        if(method != null){
            //配置了IgnoreResponseResult注解，直接返回false
            IgnoreResponseResult ignoreResponseResult = AnnotationUtil.getMethodAnnotation(method, IgnoreResponseResult.class);
            if(ignoreResponseResult != null){
                return false;
            }

            //配置了其他返回类型的话，直接返回，不进行值的处理
            RequestMapping mapping = method.getAnnotation(RequestMapping.class);
            if(mapping != null){
                String[] produces = mapping.produces();
                if(produces.length > 0){
                    return false;
                }

                String[] paths = mapping.value();
                if(paths.length > 0){
                    //如果是授权接口，返回true，因为/oauth/token接口也需要包装上外面一层。不加上这段会因为下面ResponseEntity导致返回了false
                    if("/oauth/token".equals(paths[0])){
                        return true;
                    }

                }
            }

            //判断方法的返回值
            Class<?> type = method.getReturnType();
            return !type.isAssignableFrom(Void.TYPE);
        }
        return false;
    }

    @Override
    public Object beforeBodyWrite(Object body, @NonNull MethodParameter returnType, @NonNull MediaType selectedContentType,
                                  @NonNull Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  @NonNull ServerHttpRequest request, @NonNull ServerHttpResponse response) {
        if(body instanceof Response
                || body instanceof Exception
                || body instanceof ResultError
                || body instanceof ResponseEntity){
            return body;
        }

        Method method = returnType.getMethod();
        Response<?> resp = Response.success(body);
        if(method != null){
            //判断方法的返回值,如果是字符串，将返回对象处理成字符串再返回
            Class<?> type = method.getReturnType();
            if(type.isAssignableFrom(String.class)){
                return JsonUtil.toJsonString(resp);
            }
        }
        return resp;
    }

}
